1   // Licensed under the Apache License, Version 2.0 (the "License");
2   // you may not use this file except in compliance with the License.
3   // You may obtain a copy of the License at
4   //
5   // http://www.apache.org/licenses/LICENSE-2.0
6   //
7   // Unless required by applicable law or agreed to in writing, software
8   // distributed under the License is distributed on an "AS IS" BASIS,
9   // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10  // See the License for the specific language governing permissions and
11  // limitations under the License.
12  
13  package org.apache.tapestry5.func;
14  
15  import java.util.Collection;
16  import java.util.Comparator;
17  import java.util.Iterator;
18  import java.util.Map;
19  import java.util.Map.Entry;
20  
21  /**
22   * Functional operations on collections with generics support. The core interface is {@link Flow} to
23   * which operations
24   * and transformations
25   * (in terms of {@link Predicate}s, {@link Mapper}s and {@link Reducer}s) to create new Flows. Flows
26   * are initially
27   * created
28   * using {@link #flow(Collection)} and {@link #flow(Object...)}.
29   *
30   * F will be used a bit, thus it has a short name (for those who don't like static imports). It provides a base set of
31   * Predicate, Mapper and Reducer factories. A good development pattern for applications is to provide a similar,
32   * application-specific, set of such factories.
33   *
34   * @since 5.2.0
35   */
36  @SuppressWarnings("all")
37  public class F
38  {
39      final static Flow<?> EMPTY_FLOW = new EmptyFlow();
40  
41      @SuppressWarnings("unchecked")
42      static <T> Flow<T> emptyFlow()
43      {
44          return (Flow<T>) EMPTY_FLOW;
45      }
46  
47      /**
48       * A Predicate factory for equality of an element from a flow against a specified
49       * value.
50       */
51      public static <T> Predicate<T> eql(final T value)
52      {
53          return new Predicate<T>()
54          {
55              @Override
56              public boolean accept(T element)
57              {
58                  return element.equals(value);
59              }
60          };
61      }
62  
63      /**
64       * Predicate that returns true if the provided string is blank (null or all whitespace).
65       */
66      public static Predicate<String> IS_BLANK = new Predicate<String>()
67      {
68          @Override
69          public boolean accept(String element)
70          {
71              return element == null || element.trim().length() == 0;
72          }
73      };
74  
75      /**
76       * A Predicate factory for comparison of a Comparable element from a flow against a fixed value.
77       */
78      public static <T extends Comparable<T>> Predicate<T> eq(final T value)
79      {
80          return new Predicate<T>()
81          {
82              @Override
83              public boolean accept(T element)
84              {
85                  return element.compareTo(value) == 0;
86              }
87          };
88      }
89  
90      /**
91       * A Predicate factory for comparison of a Comparable element against a fixed value.
92       */
93      public static <T extends Comparable<T>> Predicate<T> neq(final T value)
94      {
95          return new Predicate<T>()
96          {
97              @Override
98              public boolean accept(T object)
99              {
100                 return object.compareTo(value) != 0;
101             }
102         };
103     }
104 
105     /**
106      * A Predicate factory for comparison of a Comparable against a fixed value; true
107      * if the flow element is greater than the provided value.
108      */
109     public static <T extends Comparable<T>> Predicate<T> gt(final T value)
110     {
111         return new Predicate<T>()
112         {
113             @Override
114             public boolean accept(T element)
115             {
116                 return element.compareTo(value) > 0;
117             }
118         };
119     }
120 
121     /**
122      * A Predicate factory for comparison of a Comparable against a fixed value; true
123      * if the flow element is greater than or equal to the value.
124      */
125     public static <T extends Comparable<T>> Predicate<T> gteq(final T value)
126     {
127         return new Predicate<T>()
128         {
129             @Override
130             public boolean accept(T element)
131             {
132                 return element.compareTo(value) >= 0;
133             }
134         };
135     }
136 
137     /**
138      * A Predicate factory for comparison of a Comparable against a fixed value; true
139      * if the element is less than the value.
140      */
141     public static <T extends Comparable<T>> Predicate<T> lt(T value)
142     {
143         return not(gteq(value));
144     }
145 
146     /**
147      * A Predicate factory for comparison of a Comprable element against a fixed value; true
148      * if the element is less than or equal to the value.
149      */
150     public static <T extends Comparable<T>> Predicate<T> lteq(T value)
151     {
152         return not(gt(value));
153     }
154 
155     /**
156      * A Predicate factory; returns true if the value from the Flow is null.
157      */
158     public static <T> Predicate<T> isNull()
159     {
160         return new Predicate<T>()
161         {
162             @Override
163             public boolean accept(T element)
164             {
165                 return element == null;
166             }
167         };
168     }
169 
170     /**
171      * A Predicate factory; returns true if the value from the Flow is not null.
172      */
173     public static <T> Predicate<T> notNull()
174     {
175         return not(isNull());
176     }
177 
178     /**
179      * A Mapper factory that gets the string value of the flow value using {@link String#valueOf(Object)}.
180      */
181     public static <T> Mapper<T, String> stringValueOf()
182     {
183         return new Mapper<T, String>()
184         {
185             @Override
186             public String map(T value)
187             {
188                 return String.valueOf(value);
189             }
190         };
191     }
192 
193     /**
194      * A Mapper factory; the returned Mapper ignores its input value and always returns a
195      * predetermined result.
196      */
197     public static <S, T> Mapper<S, T> always(final T fixedResult)
198     {
199         return new Mapper<S, T>()
200         {
201             @Override
202             public T map(S input)
203             {
204                 return fixedResult;
205             }
206         };
207     }
208 
209     /**
210      * A Mapper factory that combines a Predicate with two {@link Mapper}s; evaluating the predicate
211      * selects one of the two mappers.
212      *
213      * @param predicate
214      *         evaluated to selected a coercion
215      * @param ifAccepted
216      *         used when predicate evaluates to true
217      * @param ifRejected
218      *         used when predicate evaluates to false
219      */
220     public static <S, T> Mapper<S, T> select(final Predicate<? super S> predicate, final Mapper<S, T> ifAccepted,
221                                              final Mapper<S, T> ifRejected)
222     {
223         assert predicate != null;
224         assert ifAccepted != null;
225         assert ifRejected != null;
226 
227         return new Mapper<S, T>()
228         {
229             @Override
230             public T map(S input)
231             {
232                 Mapper<S, T> active = predicate.accept(input) ? ifAccepted : ifRejected;
233 
234                 return active.map(input);
235             }
236         };
237     }
238 
239     /**
240      * Override of {@link #select(Predicate, Mapper, Mapper)} where rejected values are replaced
241      * with null.
242      */
243     public static <S, T> Mapper<S, T> select(Predicate<? super S> predicate, Mapper<S, T> ifAccepted)
244     {
245         return select(predicate, ifAccepted, (T) null);
246     }
247 
248     /**
249      * Override of {@link #select(Predicate, Mapper)} where rejected values are replaced with a
250      * fixed value.
251      */
252     public static <S, T> Mapper<S, T> select(Predicate<? super S> predicate, Mapper<S, T> ifAccepted, T ifRejectedValue)
253     {
254         Mapper<S, T> rejectedMapper = always(ifRejectedValue);
255 
256         return select(predicate, ifAccepted, rejectedMapper);
257     }
258 
259     /**
260      * A Mapper factory; the Mapper returns the the flow value unchanged.
261      */
262     public static <S> Mapper<S, S> identity()
263     {
264         return new Mapper<S, S>()
265         {
266             @Override
267             public S map(S input)
268             {
269                 return input;
270             }
271         };
272     }
273 
274     /**
275      * Allows a Mapper that maps to boolean to be used as a Predicate.
276      */
277     public static <S> Predicate<S> toPredicate(final Mapper<S, Boolean> mapper)
278     {
279         assert mapper != null;
280 
281         return new Predicate<S>()
282         {
283             @Override
284             public boolean accept(S object)
285             {
286                 return mapper.map(object);
287             }
288         };
289     }
290 
291     /**
292      * A Reducer that operates on a Flow of Integers and is used to sum the values.
293      */
294     public static Reducer<Integer, Integer> SUM_INTS = new Reducer<Integer, Integer>()
295     {
296         @Override
297         public Integer reduce(Integer accumulator, Integer value)
298         {
299             return accumulator + value;
300         }
301     };
302 
303     /**
304      * A two-input Mapper used to add the values from two Flows of Integers into a Flow of Integer
305      * sums.
306      */
307     public static Mapper2<Integer, Integer, Integer> ADD_INTS = new Mapper2<Integer, Integer, Integer>()
308     {
309         @Override
310         public Integer map(Integer first, Integer second)
311         {
312             return first + second;
313         }
314     };
315 
316     /**
317      * Extracts the values from the collection to form a {@link Flow}. The Collection
318      * may change after the Flow is created without affecting the Flow.
319      */
320     public static <T> Flow<T> flow(Collection<T> values)
321     {
322         assert values != null;
323 
324         if (values.isEmpty())
325             return emptyFlow();
326 
327         return new ArrayFlow<T>(values);
328     }
329 
330     /**
331      * Creates a new Flow from the values. You should not change the values array
332      * after invoking this method (i.e., no defensive copy of the values is made).
333      */
334     public static <T> Flow<T> flow(T... values)
335     {
336         if (values.length == 0)
337             return emptyFlow();
338 
339         return new ArrayFlow<T>(values);
340     }
341 
342     /**
343      * Creates a lazy Flow from the {@link Iterator} obtained from the iterable. The Flow
344      * will be threadsafe as long as the iterable yields a new Iterator on each invocation <em>and</em> the underlying
345      * iterable object is not modified while the Flow is evaluating.
346      * In other words, not extremely threadsafe.
347      */
348     public static <T> Flow<T> flow(Iterable<T> iterable)
349     {
350         assert iterable != null;
351 
352         return flow(iterable.iterator());
353     }
354 
355     /**
356      * Creates a lazy Flow from the {@link Iterator}. The Flow will be threadsafe as long as the underlying iterable
357      * object is not modified while the Flow is evaluating. In other words, not extremely threadsafe.
358      *
359      * @since 5.3
360      */
361     public static <T> Flow<T> flow(Iterator<T> iterator)
362     {
363         return lazy(new LazyIterator<T>(iterator));
364     }
365 
366     /**
367      * Creates a ZippedFlow from the provided map; the order of the tuples in the ZippedFlow is defined
368      * by the iteration order of the map entries.
369      *
370      * @param <A>
371      *         type of key and first tuple value
372      * @param <B>
373      *         type of value and second tuple value
374      * @param map
375      *         source of tuples
376      * @return zipped flow created from map
377      * @since 5.3
378      */
379     public static <A, B> ZippedFlow<A, B> zippedFlow(Map<A, B> map)
380     {
381         assert map != null;
382 
383         Flow<Tuple<A, B>> tuples = F.flow(map.entrySet()).map(new Mapper<Map.Entry<A, B>, Tuple<A, B>>()
384         {
385             @Override
386             public Tuple<A, B> map(Entry<A, B> element)
387             {
388                 return Tuple.create(element.getKey(), element.getValue());
389             }
390         });
391 
392         return ZippedFlowImpl.create(tuples);
393     }
394 
395     /**
396      * Creates a lazy Flow that returns integers in the given range. The range starts
397      * with the lower value and counts by 1 up to the upper range (which is not part of
398      * the Flow). If lower equals upper, the Flow is empty. If upper is less than lower,
399      * the Flow counts down instead.
400      *
401      * @param lower
402      *         start of range (inclusive)
403      * @param upper
404      *         end of range (exclusive)
405      */
406     public static Flow<Integer> range(int lower, int upper)
407     {
408         if (lower == upper)
409             return F.emptyFlow();
410 
411         if (lower < upper)
412             return lazy(new LazyRange(lower, upper, 1));
413 
414         return lazy(new LazyRange(lower, upper, -1));
415     }
416 
417     /**
418      * Creates a {@link Flow} from a {@linkplain LazyFunction lazy function}.
419      */
420     public static <T> Flow<T> lazy(LazyFunction<T> function)
421     {
422         assert function != null;
423 
424         return new LazyFlow<T>(function);
425     }
426 
427     private static <T> LazyFunction<T> toLazyFunction(final T currentValue, final Mapper<T, T> function)
428     {
429         return new LazyFunction<T>()
430         {
431             @Override
432             public LazyContinuation<T> next()
433             {
434                 final T nextValue = function.map(currentValue);
435 
436                 return new LazyContinuation<T>(nextValue, toLazyFunction(nextValue, function));
437             }
438         };
439     }
440 
441     /**
442      * Creates an infinite lazy flow from an initial value and a function to map from the current value to the
443      * next value.
444      *
445      * @param initial
446      *         initial value in flow
447      * @param function
448      *         maps from current value in flow to next value in flow
449      * @return lazy flow
450      */
451     public static <T> Flow<T> iterate(final T initial, final Mapper<T, T> function)
452     {
453         LazyFunction<T> head = new LazyFunction<T>()
454         {
455             @Override
456             public LazyContinuation<T> next()
457             {
458                 return new LazyContinuation<T>(initial, toLazyFunction(initial, function));
459             }
460         };
461 
462         return lazy(head);
463     }
464 
465     /**
466      * Creates an <em>infinite</em> series of numbers.
467      *
468      * Attempting to get the {@linkplain Flow#count()} of the series will form an infinite loop.
469      */
470     public static Flow<Integer> series(int start, final int delta)
471     {
472         return iterate(start, new Mapper<Integer, Integer>()
473         {
474             @Override
475             public Integer map(Integer element)
476             {
477                 return element + delta;
478             }
479         });
480     }
481 
482     /**
483      * A Worker factory; the returnedWorker adds the values to a provided collection.
484      */
485     public static <T> Worker<T> addToCollection(final Collection<T> coll)
486     {
487         return new Worker<T>()
488         {
489             @Override
490             public void work(T value)
491             {
492                 coll.add(value);
493             }
494         };
495     }
496 
497     /**
498      * A Predicate factory for matching String elements with a given prefix.
499      *
500      * @since 5.3
501      */
502     public static Predicate<String> startsWith(String prefix)
503     {
504         return startsWith(prefix, false);
505     }
506 
507     /**
508      * As {@link #startsWith(String)}, but ignores case.
509      *
510      * @since 5.3
511      */
512     public static Predicate<String> startsWithIgnoringCase(String prefix)
513     {
514         return startsWith(prefix, true);
515     }
516 
517     /**
518      * @since 5.3
519      */
520     private static Predicate<String> startsWith(final String prefix, final boolean ignoreCase)
521     {
522         return new Predicate<String>()
523         {
524             @Override
525             public boolean accept(String element)
526             {
527                 return element.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
528             }
529         };
530     }
531 
532     /**
533      * A Predicate factory for matching String elements with a given suffix.
534      *
535      * @since 5.3
536      */
537     public static Predicate<String> endsWith(String suffix)
538     {
539         return endsWith(suffix, false);
540     }
541 
542     /**
543      * As with {@link #endsWith(String)} but ignores case.
544      *
545      * @since 5.3
546      */
547     public static Predicate<String> endsWithIgnoringCase(String suffix)
548     {
549         return endsWith(suffix, true);
550     }
551 
552     /**
553      * @since 5.3
554      */
555     private static Predicate<String> endsWith(final String suffix, final boolean ignoreCase)
556     {
557         return new Predicate<String>()
558         {
559             @Override
560             public boolean accept(String element)
561             {
562                 return element
563                         .regionMatches(ignoreCase, element.length() - suffix.length(), suffix, 0, suffix.length());
564             }
565         };
566     }
567 
568     /**
569      * Creates a Comparator for the Tuples of a {@link ZippedFlow} that sorts the Tuple elements based on the first
570      * value in the Tuple.
571      *
572      * @since 5.3
573      */
574     public static <A extends Comparable<A>, B> Comparator<Tuple<A, B>> orderByFirst()
575     {
576         return new Comparator<Tuple<A, B>>()
577         {
578             @Override
579             public int compare(Tuple<A, B> o1, Tuple<A, B> o2)
580             {
581                 return o1.first.compareTo(o2.first);
582             }
583         };
584     }
585 
586     /**
587      * Creates a Comparator for the Tuples of a {@link ZippedFlow} that sorts the Tuple elements based on the first
588      * value in the Tuple.
589      *
590      * @since 5.3
591      */
592     public static <A, B extends Comparable<B>> Comparator<Tuple<A, B>> orderBySecond()
593     {
594         return new Comparator<Tuple<A, B>>()
595         {
596             @Override
597             public int compare(Tuple<A, B> o1, Tuple<A, B> o2)
598             {
599                 return o1.second.compareTo(o2.second);
600             }
601         };
602     }
603 
604     /**
605      * Inverts a predicate.
606      *
607      * @param delegate
608      *         the predicate to invert
609      * @return a new predicate that is inverse to the existing predicate
610      * @since 5.3
611      */
612     public static <T> Predicate<T> not(final Predicate<? super T> delegate)
613     {
614         assert delegate != null;
615 
616         return new Predicate<T>()
617         {
618             @Override
619             public boolean accept(T element)
620             {
621                 return !delegate.accept(element);
622             }
623         };
624     }
625 
626     /**
627      * Combines two mappers into a composite mapping from type A to type C via type B.
628      *
629      * @param abMapper
630      *         maps from A to B
631      * @param bcMapper
632      *         maps from B to C
633      * @return mapper from A to C
634      */
635     public static <A, B, C> Mapper<A, C> combine(final Mapper<A, B> abMapper, final Mapper<B, C> bcMapper)
636     {
637         assert abMapper != null;
638         assert bcMapper != null;
639 
640         return new Mapper<A, C>()
641         {
642 
643             @Override
644             public C map(A aElement)
645             {
646                 B bElement = abMapper.map(aElement);
647 
648                 return bcMapper.map(bElement);
649             }
650 
651         };
652     }
653 
654     /**
655      * Combines any number of delegates as a logical and operation. Evaluation terminates
656      * with the first delegate predicate that returns false.
657      *
658      * @param delegates
659      *         to evaluate
660      * @return combined delegate
661      * @since 5.3
662      */
663     public static <T> Predicate<T> and(final Predicate<? super T>... delegates)
664     {
665         return new Predicate<T>()
666         {
667             @Override
668             public boolean accept(T element)
669             {
670                 for (Predicate<? super T> delegate : delegates)
671                 {
672                     if (!delegate.accept(element))
673                         return false;
674                 }
675 
676                 return true;
677             }
678         };
679     }
680 
681     /**
682      * Combines any number of delegates as a logical or operation. Evaluation terminates
683      * with the first delegate predicate that returns true.
684      *
685      * @param delegates
686      *         to evaluate
687      * @return combined delegate
688      * @since 5.3
689      */
690     public static <T> Predicate<T> or(final Predicate<? super T>... delegates)
691     {
692         return new Predicate<T>()
693         {
694             @Override
695             public boolean accept(T element)
696             {
697                 for (Predicate<? super T> delegate : delegates)
698                 {
699                     if (delegate.accept(element))
700                         return true;
701                 }
702 
703                 return false;
704             }
705         };
706     }
707 
708     /**
709      * Combines several compatible workers together into a composite.
710      *
711      * @since 5.3
712      */
713     public static <T> Worker<T> combine(final Worker<? super T>... delegates)
714     {
715         assert delegates.length > 0;
716 
717         return new Worker<T>()
718         {
719             @Override
720             public void work(T value)
721             {
722                 for (Worker<? super T> delegate : delegates)
723                 {
724                     delegate.work(value);
725                 }
726             }
727         };
728     }
729 }